package com.netsdk.demo.customize;

import com.netsdk.demo.util.CaseMenu;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.ToolKits;
import com.netsdk.lib.enumeration.EM_EVENT_IVS_TYPE;
import com.netsdk.lib.enumeration.EM_EVENT_TYPE;
import com.netsdk.lib.structure.*;
import com.netsdk.lib.utils.Initialization;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Objects;

/**
 * @author 291189
 * @version 1.0
 * @description ERR220822100 
 * @date 2022/9/1 19:39
 */
public class RadarRegionDemo extends Initialization {

    int channel=0;
    NetSDKLib.LLong    attachHandle=new NetSDKLib.LLong(0);
    /**
     * 订阅智能任务
     */
    public NetSDKLib.LLong AttachEventRealLoadPic() {
        // 先退订，设备不会对重复订阅作校验，重复订阅后会有重复的事件返回
        if(attachHandle.longValue()!=0){
            this.DetachEventRealLoadPic();
        }

        // 需要图片
        int bNeedPicture = 1;
        attachHandle = netSdk.CLIENT_RealLoadPictureEx(loginHandle, channel, EM_EVENT_TYPE.EVENT_IVS_RADAR_REGION_DETECTION.getType(), bNeedPicture,
                AnalyzerDataCB.getInstance(), null, null);
        if (attachHandle.longValue() != 0) {
            System.out.printf("Chn[%d] CLIENT_RealLoadPictureEx Success\n", channel);
        } else {
            System.out.printf("Chn[%d] CLIENT_RealLoadPictureEx Failed!LastError = %s\n", channel,
                    ToolKits.getErrorCode());
        }

        return attachHandle;
    }
    /**
     * 报警事件（智能）回调
     */
    private static class AnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack {
        private final File picturePath;
        private static AnalyzerDataCB instance;

        private AnalyzerDataCB() {
            picturePath = new File("./AnalyzerPicture/");
            if (!picturePath.exists()) {
                picturePath.mkdirs();
            }
        }

        public static AnalyzerDataCB getInstance() {
            if (instance == null) {
                synchronized (AnalyzerDataCB.class) {
                    if (instance == null) {
                        instance = new AnalyzerDataCB();
                    }
                }
            }
            return instance;
        }

        @Override
        public int invoke(NetSDKLib.LLong lAnalyzerHandle, int dwAlarmType, Pointer pAlarmInfo, Pointer pBuffer, int dwBufSize,
                          Pointer dwUser, int nSequence, Pointer reserved) {
            if (lAnalyzerHandle == null || lAnalyzerHandle.longValue() == 0) {
                return -1;
            }

            switch (Objects.requireNonNull(EM_EVENT_IVS_TYPE.getEventType(dwAlarmType))) {
                case EVENT_IVS_RADAR_REGION_DETECTION : {
                    System.out.println("雷达警戒区检测事件");

                    DEV_EVENT_RADAR_REGION_DETECTION_INFO msg = new DEV_EVENT_RADAR_REGION_DETECTION_INFO();

                    ToolKits.GetPointerData(pAlarmInfo, msg);
                    /**
                     报警类型 {@link com.netsdk.lib.enumeration.EM_RADAR_ALARM_TYPE}
                     */
                    int emAlarmType = msg.emAlarmType;

                    System.out.println("emAlarmType:"+emAlarmType);



                    /**
                     触发事件目标的id,范围[0,63]
                     */
                    System.out.println("nTrackID:"+msg.nTrackID);
                    /**
                     触发事件目标的速度，用整型传输，扩大100倍 单位m/s
                     */
                    System.out.println("nSpeed:"+msg.nSpeed);
/**
 触发事件目标的类型的掩码: 0x00未识别目标 0x01目标为人 0x02目标为交通工具 0x03目标为树 0x04目标为建筑物 0x05目标为屏幕 0x06目标为动物 0x07目标为大船 0x08目标为中船 0x09目标为小船
 */
                    System.out.println("nObjectType:"+msg.nObjectType);
                    /**
                     当前触发事件目标的像素极坐标值--距离，扩大100倍的结果,单位米
                     */
                    System.out.println("nDistance:"+msg.nDistance);
                    /**
                     当前触发事件目标的极坐标值--角度，扩大100倍的结果，单位度
                     */
                    System.out.println("nAngle:"+msg.nAngle);


                    /**
                     报警等级
                     */
                    byte[] szAlarmLevel = msg.szAlarmLevel;
                    try {
                        System.out.println("szAlarmLevel:"+new String(szAlarmLevel,encode));
                        /**
                         报警输入通道号
                         */
                        System.out.println("nAlarmChannel:"+msg.nAlarmChannel);
                        /**
                         RFID卡片信息个数
                         */
                        int nRFIDCardIdNum = msg.nRFIDCardIdNum;
                        System.out.println("nRFIDCardIdNum:"+nRFIDCardIdNum);


                        NET_RFID_CARD_INFO[] stuRFIDCardId = msg.stuRFIDCardId;

                        for (int i=0;i<nRFIDCardIdNum;i++){
                            NET_RFID_CARD_INFO info = stuRFIDCardId[i];


                            byte[] szCardId = info.szCardId;

                            System.out.println("szCardId:"+new String(szCardId,encode));
                        }

                        int nstuSceneImageExNum = msg.nstuSceneImageExNum;

                        NetSDKLib.SCENE_IMAGE_INFO_EX[] stuSceneImageEx = msg.stuSceneImageEx;


                        for(int i=0;i<nstuSceneImageExNum;i++){
                            NetSDKLib.SCENE_IMAGE_INFO_EX stuSceneImage = stuSceneImageEx[i];

                            //图片
                            if (stuSceneImage != null && stuSceneImage.nLength > 0) {
                                String picture = picturePath + "/" + System.currentTimeMillis() + "_stuImgaeInfo.jpg";
                                ToolKits.savePicture(pBuffer, stuSceneImage.nOffSet, stuSceneImage.nLength, picture);
                            }
                        }

                        int nDistance = msg.nDistance;
                        System.out.println("nDistance:"+nDistance);
                        int nAngle = msg.nAngle;
                        System.out.println("nAngle:"+nAngle);

                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }


                    break;
                }
                default:
                    System.out.println("其他事件--------------------"+ dwAlarmType);
                    break;
            }
            return 0;
        }
    }


    /**
     * 停止侦听智能事件
     */
    public void DetachEventRealLoadPic() {
        if (this.attachHandle.longValue() != 0) {
            netSdk.CLIENT_StopLoadPic(this.attachHandle);
        }
    }


    /**
     * 订阅报警信息
     *
     */
    public void startListen() {



        // 设置报警回调函数
        netSdk.CLIENT_SetDVRMessCallBack(fAlarmAccessDataCB.getInstance(), null);

        // 订阅报警
        boolean bRet = netSdk.CLIENT_StartListenEx(loginHandle);
        if (!bRet) {
            System.err.println("订阅报警失败! LastError = 0x%x\n" + netSdk.CLIENT_GetLastError());
        } else {
            System.out.println("订阅报警成功.");
        }
    }

    /**
     * 报警事件回调
     */
    private static class fAlarmAccessDataCB implements NetSDKLib.fMessCallBack {
        private static fAlarmAccessDataCB instance = new fAlarmAccessDataCB();

        private fAlarmAccessDataCB() {
        }

        public static fAlarmAccessDataCB getInstance() {
            return instance;
        }

        @Override
		public boolean invoke(int lCommand, NetSDKLib.LLong lLoginID, Pointer pStuEvent, int dwBufLen, String strDeviceIP,
                              NativeLong nDevicePort, Pointer dwUser) {
            switch (lCommand) {
                case NetSDKLib.NET_ALARM_RADAR_REGIONDETECTION: {// 雷达区域检测事件(对应结构体 ALARM_RADAR_REGIONDETECTION_INFO)

                    ALARM_RADAR_REGIONDETECTION_INFO msg = new ALARM_RADAR_REGIONDETECTION_INFO();
                    ToolKits.GetPointerData(pStuEvent, msg);
                    System.out.println(" 雷达区域检测事件 时间(UTC):" + msg.stuTime.toStringTime() +
                            " 通道号:" + msg.nChannelID +" RFID卡片数量:" + msg.nCardNum+" 报警等级:" + msg.nAlarmLevel);

                    /**
                     触发事件目标的id,范围[0,63]
                     */
                    System.out.println("nTrackID:"+msg.nTrackID);
                    /**
                     触发事件目标的速度，用整型传输，扩大100倍 单位m/s
                     */
                    System.out.println("nSpeed:"+msg.nSpeed);
/**
 触发事件目标的类型的掩码: 0x00未识别目标 0x01目标为人 0x02目标为交通工具 0x03目标为树 0x04目标为建筑物 0x05目标为屏幕 0x06目标为动物 0x07目标为大船 0x08目标为中船 0x09目标为小船
 */
                    System.out.println("nObjectType:"+msg.nObjectType);
                        /**
                         当前触发事件目标的像素极坐标值--距离，扩大100倍的结果,单位米
                         */
                    System.out.println("nDistance:"+msg.nDistance);
                         /**
                          当前触发事件目标的极坐标值--角度，扩大100倍的结果，单位度
                         */
                    System.out.println("nAngle:"+msg.nAngle);
                    NET_RADAR_REGIONDETECTION_RFIDCARD_INFO[] stuCardInfo = msg.stuCardInfo;
                    try {
                        System.out.println("----------------卡片ID开始----------------");
                        for (int i = 0; i < msg.nCardNum; i++) {
                            System.out.println("卡片ID[：" +(i+1)+"]"+ new String(stuCardInfo[i].szCardID, encode));
                        }
                        System.out.println("----------------卡片ID结束----------------");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
            /**
             当前触发事件目标的像素极坐标值--距离，扩大100倍的结果,单位米
             */
                    int nDistance = msg.nDistance;

                    System.out.println("nDistance:"+nDistance);
                    int nAngle = msg.nAngle;
                    System.out.println("nAngle:"+nAngle);

                    break;
                }
            }
            return true;
        }
    }

    /**
     * 取消订阅报警信息
     *
     * @return
     */
    public void stopListen() {
        // 停止订阅报警
        boolean bRet = netSdk.CLIENT_StopListen(loginHandle);
        if (bRet) {
            System.out.println("取消订阅报警信息.");
        }
    }

    // 订阅句柄
    private static NetSDKLib.LLong RadarAlarmHandle = new NetSDKLib.LLong(0);
    //订阅雷达的报警点信息
    public void attachRadarAlarmInfo() {

        // 先退订，设备不会对重复订阅作校验，重复订阅后会有重复的事件返回
        if(RadarAlarmHandle.longValue()!=0){
            this.detachRadarAlarmInfo();
        }

        NET_IN_RADAR_ALARMPOINTINFO pIn = new NET_IN_RADAR_ALARMPOINTINFO();
        pIn.nChannel = 0;
        pIn.cbAlarmPointInfo = CBRadarAlarmPointInfoCallBack.getInstance();
        pIn.write();
        NET_OUT_RADAR_ALARMPOINTINFO pOut = new NET_OUT_RADAR_ALARMPOINTINFO();
        pOut.write();
        RadarAlarmHandle = netSdk.CLIENT_AttachRadarAlarmPointInfo(loginHandle, pIn.getPointer(), pOut.getPointer(), 3000);
        if (RadarAlarmHandle.longValue() == 0) {
            System.out.printf("attachDadarAlarmInfo fail, ErrCode=%x\n", netSdk.CLIENT_GetLastError());
        } else {
            System.out.println("attachDadarAlarmInfo success");
        }
    }

    public void detachRadarAlarmInfo() {
        if (RadarAlarmHandle.longValue() != 0) {
            netSdk.CLIENT_DetachRadarAlarmPointInfo(RadarAlarmHandle);
        } else {
            System.out.println("订阅句柄为空,请先订阅");
        }
    }

    /**
     * 雷达报警点信息回调
     */
    private static class CBRadarAlarmPointInfoCallBack implements NetSDKLib.fRadarAlarmPointInfoCallBack {

        private CBRadarAlarmPointInfoCallBack() {
        }

        private static class CallBackHolder {
            private static CBRadarAlarmPointInfoCallBack instance = new CBRadarAlarmPointInfoCallBack();
        }

        public static CBRadarAlarmPointInfoCallBack getInstance() {
            return CallBackHolder.instance;
        }

        @Override
        public void invoke(NetSDKLib.LLong lLoginId, NetSDKLib.LLong lAttachHandle, Pointer pBuf, int dwBufLen, Pointer pReserved,
                           Pointer dwUser) {
            System.out.println("雷达报警点信息回调");
            // TODO Auto-generated method stub
            NET_RADAR_NOTIFY_ALARMPOINTINFO radarInfo = new NET_RADAR_NOTIFY_ALARMPOINTINFO();
            ToolKits.GetPointerData(pBuf, radarInfo);
            for (int i = 0; i < radarInfo.nNumAlarmPoint; i++) {
                System.out.println("通道号:" + radarInfo.nChannel + "\n点类型:" + radarInfo.stuAlarmPoint[i].nPointType
                        + "\n当前点所属的防区编号:" + radarInfo.stuAlarmPoint[i].nRegionNumber + "\n点所指对象的类型:"
                        + radarInfo.stuAlarmPoint[i].emObjectType + "\n点所属的轨迹号:" + radarInfo.stuAlarmPoint[i].nTrackID
                        + "\n当前点像素极坐标值-距离:" + radarInfo.stuAlarmPoint[i].nDistance + "\n当前点像素极坐标值-角度:"
                        + radarInfo.stuAlarmPoint[i].nAngle +
                        "\n正在跟踪目标的球机的IP地址:" + new String(radarInfo.stuAlarmPoint[i].szTrackerIP)
                        +"\n当前点速度:" + radarInfo.stuAlarmPoint[i].nSpeed + "\n\n");
            }

        }
    }

public void RunTest()
{
    System.out.println("Run Test");
    CaseMenu menu = new CaseMenu();;
    menu.addItem((new CaseMenu.Item(this , "AttachEventRealLoadPic" , "AttachEventRealLoadPic")));
    menu.addItem((new CaseMenu.Item(this , "DetachEventRealLoadPic" , "DetachEventRealLoadPic")));

    menu.addItem((new CaseMenu.Item(this , "startListen" , "startListen")));
    menu.addItem((new CaseMenu.Item(this , "stopListen" , "stopListen")));

    menu.addItem((new CaseMenu.Item(this , "attachRadarAlarmInfo" , "attachRadarAlarmInfo")));
    menu.addItem((new CaseMenu.Item(this , "detachRadarAlarmInfo" , "detachRadarAlarmInfo")));

    menu.run();
}

    public static void main(String[] args) {
        RadarRegionDemo radarDemo=new RadarRegionDemo();
        InitTest("10.11.9.191",37777,"admin","admin456");
        radarDemo.RunTest();
        LoginOut();

    }


}
